package org.jaronsource.framework.core.service;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.jaronsource.framework.core.dao.support.Criteria;
import org.jaronsource.framework.core.dao.support.IEntity;
import org.jaronsource.framework.core.dao.support.IGenericDao;
import org.jaronsource.framework.core.dao.support.Page;
import org.jaronsource.framework.core.dao.support.PageRequest;
import org.jaronsource.framework.core.dao.support.Sort;

/**
 * 泛型Service接口
 * 
 * @author Jaron
 * 
 * @param <T>
 * @param <I>
 */
public interface IGenericService<T extends IEntity<I>, I extends Serializable>
		extends IService {

	/**
	 * 得到IDao实例
	 * 
	 * @return IDao实例
	 */
	IGenericDao<T, I> getDao();

	/**
	 * <p>
	 * 保存对象
	 * 
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Foo foo1 = new Foo();
	 * fooService.save( foo1 );
	 * </pre>
	 * 
	 * @param target 待保存的对象
	 * @return 已保存的对象
	 */
	T save( T target );

	/**
	 * <p>
	 * 一次保存任意多个对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Foo foo1 = new Foo(); Foo foo2 = new Foo(); ... fooService.save(foo1, foo2, ...);
	 * </pre>
	 * 
	 * @param targets 待保存的对象（任意个数，用","号分隔开）
	 * @return 已保存对象的数组
	 */
	T[] save( T... targets );
	
	/**
	 * <p> 更新对象，只更新非null得属性
	 * 
	 * <p> 示例：
	 * 
	 * <pre> Foo foo1 = new Foo(); fooService.update( foo1, 1 ); </pre>
	 * 
	 * @param target 待更新的对象
	 * @return 已更新的对象
	 */
	void update( T target, I pk );

	/**
	 * <p>
	 * 按id删除对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * int id = 1;
	 * fooService.remove( id );
	 * </pre>
	 * 
	 * @param id 待删除对象的id
	 */
	void remove( I id );

	/**
	 * <p>
	 * 一次删除任意多个对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * fooService.remove( 1, 2, 3 );
	 * </pre>
	 * 
	 * @param id 待删除对象的id（任意个数，用","号分隔开）
	 */
	void remove( I... ids );

	/**
	 * <p>
	 * 检查对象是否在数据库中存在
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * int id = 1;
	 * fooService.exists( id );
	 * </pre>
	 * 
	 * @param id 待检查对象的id
	 * @return 是否在数据库中存在
	 */
	boolean exists( I id );

	/**
	 * <p>
	 * 按主键查找对象引用， 如果对象已在持久化上下文中，直接返回此对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Foo foo = fooService.findReferenceByPk( id );
	 * </pre>
	 * 
	 * @param id 主键
	 * @return 返回找到的对象引用
	 */
	T findReferenceByPk( I id );

	/**
	 * <p>
	 * 按主键查找对象， 如果对象已在持久化上下文中，直接返回此对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Foo foo = fooService.findByPk( id );
	 * </pre>
	 * 
	 * @param id 主键
	 * @return 返回找到的对象 或 null
	 */
	T findByPk( I id );

	/**
	 * <p>
	 * 根据查询条件，查出第一个符合条件的对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Criteria criteria = new Criteria();
	 * criteria.addEntry( &quot;name&quot;, Op.EQ, &quot;name1&quot; );
	 * 
	 * Foo foo = fooService.findOne( criteria );
	 * </pre>
	 * 
	 * @param criteria 查询条件
	 * @return 符合查询条件的第一个对象 或 null
	 */
	T findOne( Criteria criteria );

	/**
	 * <p>
	 * 根据查询条件，查出第一个符合条件的对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; );
	 * Criteria criteria = new Criteria();
	 * criteria.addEntry( &quot;name&quot;, Op.EQ, &quot;name1&quot; );
	 * 
	 * Foo foo = fooService.findOne( sort, criteria );
	 * </pre>
	 * 
	 * @param sort 排序条件
	 * @param criteria 查询条件
	 * @return 符合查询条件的第一个对象 或 null
	 */
	T findOne( Sort sort, Criteria criteria );

	/**
	 * <p>
	 * 使用jpql语句，查出第一个符合条件的对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * String jpql = &quot;select o from Foo o where o.name = ?&quot;;
	 * Foo foo = fooService.findOne( jpql, &quot;name1&quot; );
	 * </pre>
	 * 
	 * @param jpql jpql查询语句
	 * @param params jpql参数
	 * @return 符合查询条件的第一个对象 或 null
	 */
	T findOne( String jpql, Object... params );

	/**
	 * <p>
	 * 使用jpql语句，查出第一个符合条件的对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * String jpql = &quot;select o from Foo o where o.name = :name&quot;;
	 * Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;();
	 * params.put( &quot;name&quot;, &quot;name1&quot; );
	 * Foo foo = fooService.findOne( jpql, params );
	 * </pre>
	 * 
	 * @param jpql jpql查询语句
	 * @param params jpql参数
	 * @return 符合查询条件的第一个对象 或 null
	 */
	T findOne( String jpql, Map<String, ?> params );

	/**
	 * <p>
	 * 使用jpql语句，查出第一个符合条件的对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; ); String jpql = &quot;select o from Foo o where o.name =
	 * ?&quot;; Foo foo = fooService.findOne( sort, jpql, &quot;name1&quot; );
	 * </pre>
	 * 
	 * @param sort 排序条件
	 * @param jpql jpql查询语句
	 * @param params jpql参数
	 * @return 符合查询条件的第一个对象 或 null
	 */
	T findOne( Sort sort, String jpql, Object... params );

	/**
	 * <p>
	 * 使用jpql语句，查出第一个符合条件的对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; ); String jpql = &quot;select o from Foo o where o.name =
	 * :name&quot;; Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;(); params.put(
	 * &quot;name&quot;, &quot;name1&quot; ); Foo foo = fooService.findOne( sort, jpql, params );
	 * </pre>
	 * 
	 * @param sort 排序条件
	 * @param jpql jpql查询语句
	 * @param params jpql参数
	 * @return 符合查询条件的第一个对象 或 null
	 */
	T findOne( Sort sort, String jpql, Map<String, ?> params );

	/**
	 * 查出所有对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * List&lt;Foo&gt; fooList = fooService.findAll();
	 * </pre>
	 * 
	 * @return 所有对象的List
	 */
	List<T> findAll();

	/**
	 * 查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * String criteria = new Criteria();
	 * List&lt;Foo&gt; fooList = fooService.find( criteria );
	 * </pre>
	 * 
	 * @param criteria 查询条件
	 * @return 符合条件的对象集合
	 */
	List<T> find( Criteria criteria );

	/**
	 * 使用jpql语句，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * String jpql = &quot;select o from Foo o where o.name like ?&quot;;
	 * List&lt;Foo&gt; fooList = fooService.find( jpql, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * </pre>
	 * 
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	List<T> find( String jpql, Object... params );

	/**
	 * 使用jpql语句，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * String jpql = &quot;select o from Foo o where o.name like :name&quot;;
	 * Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;();
	 * params.put( &quot;name&quot;, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * List&lt;Foo&gt; fooList = fooService.find( jpql, params );
	 * </pre>
	 * 
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	List<T> find( String jpql, Map<String, ?> params );

	/**
	 * 使用 排序条件、查询条件，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; );
	 * Criteria criteria = new Criteria();
	 * criteria.addEntry( &quot;name&quot;, Op.EQ, &quot;name1&quot; );
	 * 
	 * List&lt;Foo&gt; fooList = fooService.find( sort, criteria );
	 * </pre>
	 * 
	 * @param sort 排序条件
	 * @param criteria 查询条件
	 * @return 符合条件的对象集合
	 */
	List<T> find( Sort sort, Criteria criteria );

	/**
	 * 使用 分页条件、查询条件，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; );
	 * PageRequest pageRequest = new PageRequest( 1, 10, sort );
	 * 
	 * Criteria criteria = new Criteria();
	 * criteria.addEntry( &quot;name&quot;, Op.EQ, &quot;name1&quot; );
	 * 
	 * List&lt;Foo&gt; fooList = fooService.find( pageRequest, criteria );
	 * </pre>
	 * 
	 * @see PageRequest
	 * @param pageRequest 分页条件
	 * @param criteria 查询条件
	 * @return 符合条件的对象集合
	 */
	List<T> find( PageRequest pageRequest, Criteria criteria );

	/**
	 * 使用 排序条件、jpql语句，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; ); String jpql = &quot;select o from Foo o where o.name like
	 * ?&quot;; List&lt;Foo&gt; fooList = fooService.find( sort, jpql, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * </pre>
	 * 
	 * @param sort 排序条件
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	List<T> find( Sort sort, String jpql, Object... params );

	/**
	 * 使用 排序条件、jpql语句，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; ); String jpql = &quot;select o from Foo o where o.name like
	 * :name&quot;; Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;(); params.put(
	 * &quot;name&quot;, &quot;name1&quot;.concat( &quot;%&quot; ) ); List&lt;Foo&gt; fooList = fooService.find( sort,
	 * jpql, params );
	 * </pre>
	 * 
	 * @param sort 排序条件
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	List<T> find( Sort sort, String jpql, Map<String, ?> params );

	/**
	 * 使用 分页条件、jpql语句，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * </pre> Sort sort = new Sort().asc("name"); PageRequest pageRequest = new
	 * PageRequest(1, 10, sort);
	 * 
	 * String jpql = "select o from Foo o where o.name like ?"; List<Foo>
	 * fooList = fooService.find(pageRequest, jpql, "name1".concat("%")); </pre>
	 * 
	 * @param pageRequest 分页条件
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	List<T> find( PageRequest pageRequest, String jpql, Object... params );

	/**
	 * 使用 分页条件、jpql语句，查出符合条件的对象集合
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; );
	 * PageRequest pageRequest = new PageRequest( 1, 10, sort );
	 * 
	 * String jpql = &quot;select o from Foo o where o.name like :name&quot;;
	 * Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;();
	 * params.put( &quot;name&quot;, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * List&lt;Foo&gt; fooList = fooService.find( pageRequest, jpql, params );
	 * </pre>
	 * 
	 * @param pageRequest 分页条件
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	List<T> find( PageRequest pageRequest, String jpql, Map<String, ?> params );

	/**
	 * 使用 查询条件，查出符合条件的对象数量
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Criteria criteria = new Criteria();
	 * criteria.addEntry( &quot;name&quot;, Op.EQ, &quot;name1&quot; );
	 * 
	 * long count = fooService.count( criteria );
	 * </pre>
	 * 
	 * @param criteria 查询条件
	 * @return 符合条件的对象数量
	 */
	long count( Criteria criteria );

	/**
	 * 使用 jpql语句，查出符合条件的对象数量
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * String jpql = &quot;select o from Foo o where o.name like ?&quot;;
	 * long count = fooService.count( jpql, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * </pre>
	 * 
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	long count( String jpql, Object... params );

	/**
	 * 使用 jpql语句，查出符合条件的对象数量
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * String jpql = &quot;select o from Foo o where o.name like :name&quot;;
	 * Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;();
	 * params.put( &quot;name&quot;, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * long count = fooService.count( jpql, params );
	 * </pre>
	 * 
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的对象集合
	 */
	long count( String jpql, Map<String, ?> params );

	/**
	 * 使用 分页条件、查询条件，查出符合条件的分页对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; );
	 * PageRequest pageRequest = new PageRequest( 1, 10, sort );
	 * 
	 * Criteria criteria = new Criteria();
	 * criteria.addEntry( &quot;name&quot;, Op.EQ, &quot;name1&quot; );
	 * 
	 * Page&lt;Foo&gt; fooPage = fooService.findPage( pageRequest, criteria );
	 * </pre>
	 * 
	 * @param pageRequest 分页条件
	 * @param criteria 查询条件
	 * @return 符合条件的分页对象
	 */
	Page<T> findPage( PageRequest pageRequest, Criteria criteria );

	/**
	 * 使用 分页条件、jpql语句，查出符合条件的分页对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; );
	 * PageRequest pageRequest = new PageRequest( 1, 10, sort );
	 * 
	 * String jpql = &quot;select o from Foo o where o.name like ?&quot;;
	 * Page&lt;Foo&gt; fooPage = fooService.findPage( pageRequest, jpql, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * </pre>
	 * 
	 * @param pageRequest 分页条件
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的分页对象
	 */
	Page<T> findPage( PageRequest pageRequest, String jpql, Object... params );

	/**
	 * 使用 分页条件、jpql语句，查出符合条件的分页对象
	 * <p>
	 * 示例：
	 * 
	 * <pre>
	 * Sort sort = new Sort().asc( &quot;name&quot; );
	 * PageRequest pageRequest = new PageRequest( 1, 10, sort );
	 * 
	 * String jpql = &quot;select o from Foo o where o.name like :name&quot;;
	 * Map&lt;String, Object&gt; params = new HashMap&lt;String, Object&gt;();
	 * params.put( &quot;name&quot;, &quot;name1&quot;.concat( &quot;%&quot; ) );
	 * Page&lt;Foo&gt; fooPage = fooService.findPage( pageRequest, jpql, params );
	 * </pre>
	 * 
	 * @param pageRequest 分页条件
	 * @param jpql jpql语句
	 * @param params jpql参数
	 * @return 符合条件的分页对象
	 */
	Page<T> findPage(	PageRequest pageRequest,
						String jpql,
						Map<String, ?> params );

}
